home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Night Owl 8
/
Night Owl CD-ROM (NOPV8) (Night Owl Publisher) (1993).ISO
/
047a
/
lex_yacc.arj
/
LEXLIB.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1990-01-14
|
9KB
|
228 lines
unit LexLib;
(* Library of supplementing routines for Lex generated lexical analysers.
V1.1 9-29-88 AG
V2.0 2-28-89, 5-28-89 AG *)
interface
(* The Lex library defines
- the default input and output streams to be used by a generated
lexical analyser yylex (these defaults may be overwritten by
appropriate declarations in the user program or Lex specification)
- the default yylex error handler yyloverflow; this routine can be
overwritten by an appropriate user-defined procedure *)
(* Default I/O streams: **************************************************)
(* The default input/output streams are implemented as Pascal text files
that are initialized to read from standard input and write to standard
output, allowing for DOS I/O redirection and piping. The I/O streams may
also be redirected and manipulated by using the appropriate Turbo Pascal
file routines (assign, reset, rewrite, close, ...) on yyin and yyout.
Furthermore, if the I/O streams to be used are something other
than MS-DOS files and devices (e.g. internal memory), the procedures
listed below can be replaced altogether by suitable user defined
routines with compatible specifications, since yylex uses only the
routines input, output, unput and yywrap and does not access the
I/O files directly.
yyin and yyout are closed automatically at the end of the main
program; however, if you want to process multiple files in sequence, you
will have to close, reassign and reopen the files explicitly (and also
reinitialize yylineno appropriately, if you intend to use it).
Error handling: the result of the latest LexLib I/O operation is stored
in the yyioresult variable; in case of an error (yyioresult<>0) yyin will
return #0 (end-of-file).
A nonzero value of yyioresult can be used to determine the nature of an
error (refer to the description of `ioresult' in the Turbo Pascal
documentation). *)
var
yyin, yyout : Text;
(* default I/O streams; initialized to standard input and output *)
yyioresult : integer;
(* result of last I/O operation *)
yylineno : integer;
(* current line number, initialized to 1 and updated automatically
by input and unput *)
function input : char;
(* read a character from the input stream; return #0 for
end-of-file; convert line end (<CR><LF>) to newline (\n) *)
procedure output(c : char);
(* write a character on the output stream; convert newline (\n) to
<CR><LF> *)
procedure unput(c : char);
(* return c to the input stream to be reread by subsequent calls to
yyin; the current implementation of unput is restricted to
255 characters max; if this restriction is violated unput will
call LexLib.yyloverflow *)
function yywrap : boolean;
(* this routine is called by yylex at end of input to determine whether
to terminate lexical analysis and perform the normal wrapup (return
end-of-file, etc.); the standard version of yywrap always returns
TRUE, indicating that yylex should perform normal wrapup.
This routine may be redefined to do application dependent processing
at end-of-file; in particular, it can arrange for more input and
return FALSE in which case yylex will continue lexical analysis. *)
(* Error handler: ********************************************************)
function yyloverflow : boolean;
(* Called by yylex in case of input buffer overflow; this default version
prints an error message and returns TRUE indicating a non-recoverable
overflow which causes yylex to terminate the program with errorlevel 1.
yyloverflow may be redefined to print a more appropriate error message,
or do some other processing. In particular, it may inspect and
manipulate the input stream (e.g. insert a character that will
terminate the current match), and return FALSE to yylex, in which case
yylex will automatically recover from the overflow error (yylex will
obtain the next input character, and if that character does not
already terminate the match, will append the character to the match
and assume that now the next input character cannot be accepted).
NOTE: This routine is *nonstandard*, i.e. not provided by UNIX Lex
versions. *)
(* procedures and variables defined by yylex: ****************************)
(* the following user procedures and variables are not defined by the Lex
library, but are declared directly in the Lex output file (they are
compatible with the corresponding UNIX Lex routines and macros):
var
yytext : string[yylbufsize];
{ text of token previously matched by yylex }
yyleng : Byte;
{ current length of yytext (last character in yytext is
yytext[yyleng]) }
procedure yymore;
{ extend the current match by appending the next match to the current
token in yytext }
procedure yyless(n : integer);
{ only retain the first n characters from the current match in yytext;
return all other characters to the input stream }
procedure reject;
{ reject the current match and process whatever rule was second
choice after the current rule; this routine may be used to detect
items that overlap or include each other }
procedure begin_(s : integer);
{ put yylex in start state s (0: initial start state; <id>: start
state defined by %start <id> declaration (note the underscore
at the end of the name of this routine!) }
procedure return(tok : integer);
{ sets tok as the return value for yylex and causes yylex to exit
as soon as all actions of the current rule have been executed (to
exit from an action - but not automatically from yylex -, the Turbo-
Pascal standard procedure exit may be used); this routine is
provided as a sort of `replacement' for the C return statement }
procedure echo;
{ echo the matched token in yytext to the output } *)
implementation
{$I-}
var nextExitProc : Pointer;
(* pointer to next exit procedure *)
{$F+}
procedure yylexit;
{$F-}
(* LexLib exit procedure; MUST be called FAR *)
begin
close(yyin); if ioresult<>0 then ;
close(yyout); if ioresult<>0 then ;
exitProc := nextExitProc (* chain to next exit procedure *)
end(*yylexit*);
(* character codes: *)
const
LF = #10; (* line feed *)
CR = #13; (* carriage return *)
NEWLINE = LF; (* newline character *)
(* The default I/O streams are implemented in terms of the text files
yyin and yyout. unput is implemented via a string buffer
yybuf.
input needs lookahead itself in order to determine line ends <CR><LF>;
this lookahead is also handled with unput. *)
var
yybuf : string;
yybufleng : Byte absolute yybuf;
(* buffer holding input to be reread (unput) *)
function input : char;
var c : char;
begin
if yybufleng>0 then
begin
if yybuf[yybufleng]=NEWLINE then
inc(yylineno);
input := yybuf[yybufleng];
dec(yybufleng)
end
else if eof(yyin) then
input := #0
else
begin
read(yyin, c);
yyioresult := ioresult;
if yyioresult<>0 then
input := #0
else if (c=CR) and not eof(yyin) then
begin
read(yyin, c);
if c=LF then
begin
inc(yylineno);
input := NEWLINE
end
else
begin
unput(c);
input := CR
end
end
else
input := c;
end;
yyioresult := ioresult;
if yyioresult<>0 then
input := #0
end(*input*);
procedure output(c : char);
begin
if c=NEWLINE then
(* convert NEWLINE to <CR><LF> *)
write(yyout, CR, LF)
else
write(yyout, c);
yyioresult := ioresult
end(*output*);
procedure unput(c : char);
begin
if yybufleng=255 then
if yyloverflow then halt(1) else
else
begin
inc(yybufleng);
yybuf[yybufleng] := c;
if c=NEWLINE then
dec(yylineno)
end
end(*unput*);
function yywrap : boolean;
begin
yywrap := true
end(*yywrap*);
function yyloverflow : boolean;
begin
writeln('yylex: buffer overflow');
yyloverflow := true
end(*yyloverflow*);
begin
(* obtain current exit procedure chain: *)
nextExitProc := exitProc;
(* install LexLib exit procedure: *)
exitProc := @yylexit;
(* assign yyin and yyout to stdin and stdout, respectively *)
assign(yyin, ''); assign(yyout, '');
reset(yyin); rewrite(yyout);
yyioresult := ioresult;
yybuf := '';
yylineno := 1
end(*LexLib*).